<template>
  <div class="search-form">
    <el-form
      ref="formRef"
      :model="searchData"
      :inline="inline"
      :label-width="labelWidth"
      :size="size"
    >
      <template v-for="field in visibleFields" :key="field.prop">
        <el-form-item :label="field.label" :prop="field.prop">
          <!-- 输入框 -->
          <el-input
            v-if="field.type === 'input'"
            v-model="searchData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :clearable="field.clearable !== false"
            :style="{ width: field.width || '200px' }"
            @keyup.enter="handleSearch"
          />
          
          <!-- 选择器 -->
          <el-select
            v-else-if="field.type === 'select'"
            v-model="searchData[field.prop]"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :clearable="field.clearable !== false"
            :multiple="field.multiple"
            :filterable="field.filterable"
            :style="{ width: field.width || '200px' }"
          >
            <el-option
              v-for="option in field.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
              :disabled="option.disabled"
            />
          </el-select>
          
          <!-- 日期选择器 -->
          <el-date-picker
            v-else-if="field.type === 'date'"
            v-model="searchData[field.prop]"
            :type="field.dateType || 'date'"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :clearable="field.clearable !== false"
            :format="field.format"
            :value-format="field.valueFormat"
            :style="{ width: field.width || '200px' }"
          />
          
          <!-- 日期范围选择器 -->
          <el-date-picker
            v-else-if="field.type === 'daterange'"
            v-model="searchData[field.prop]"
            type="daterange"
            :range-separator="field.rangeSeparator || '至'"
            :start-placeholder="field.startPlaceholder || '开始日期'"
            :end-placeholder="field.endPlaceholder || '结束日期'"
            :clearable="field.clearable !== false"
            :format="field.format"
            :value-format="field.valueFormat"
            :style="{ width: field.width || '240px' }"
          />
          
          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="field.type === 'number'"
            v-model="searchData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :min="field.min"
            :max="field.max"
            :step="field.step"
            :precision="field.precision"
            :style="{ width: field.width || '200px' }"
          />
          
          <!-- 自定义插槽 -->
          <slot
            v-else-if="field.type === 'slot'"
            :name="field.prop"
            :field="field"
            :value="searchData[field.prop]"
            :search-data="searchData"
          />
        </el-form-item>
      </template>
      
      <!-- 操作按钮 -->
      <el-form-item>
        <el-button type="primary" @click="handleSearch" :loading="searchLoading">
          <el-icon><Search /></el-icon>
          搜索
        </el-button>
        <el-button @click="handleReset">
          <el-icon><Refresh /></el-icon>
          重置
        </el-button>
        <el-button
          v-if="collapsible && fields.length > collapseCount"
          type="text"
          @click="toggleCollapse"
        >
          {{ collapsed ? '展开' : '收起' }}
          <el-icon>
            <ArrowDown v-if="collapsed" />
            <ArrowUp v-else />
          </el-icon>
        </el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { Search, Refresh, ArrowDown, ArrowUp } from '@element-plus/icons-vue'
import type { FormInstance } from 'element-plus'

export interface SearchField {
  prop: string
  label: string
  type: 'input' | 'select' | 'date' | 'daterange' | 'number' | 'slot'
  placeholder?: string
  clearable?: boolean
  width?: string
  
  // select 相关
  options?: Array<{ label: string; value: any; disabled?: boolean }>
  multiple?: boolean
  filterable?: boolean
  
  // date 相关
  dateType?: string
  format?: string
  valueFormat?: string
  rangeSeparator?: string
  startPlaceholder?: string
  endPlaceholder?: string
  
  // number 相关
  min?: number
  max?: number
  step?: number
  precision?: number
}

interface Props {
  fields: SearchField[]
  modelValue?: Record<string, any>
  inline?: boolean
  labelWidth?: string
  size?: 'large' | 'default' | 'small'
  searchLoading?: boolean
  collapsible?: boolean
  collapseCount?: number
}

const props = withDefaults(defineProps<Props>(), {
  fields: () => [],
  modelValue: () => ({}),
  inline: true,
  labelWidth: '80px',
  size: 'default',
  searchLoading: false,
  collapsible: true,
  collapseCount: 3
})

const emit = defineEmits<{
  'update:modelValue': [value: Record<string, any>]
  search: [searchData: Record<string, any>]
  reset: []
}>()

const formRef = ref<FormInstance>()
const searchData = reactive<Record<string, any>>({})
const collapsed = ref(true)

// 可见字段
const visibleFields = computed(() => {
  if (!props.collapsible || !collapsed.value) {
    return props.fields
  }
  return props.fields.slice(0, props.collapseCount)
})

// 监听 modelValue 变化
watch(() => props.modelValue, (newValue) => {
  Object.assign(searchData, newValue)
}, { immediate: true, deep: true })

// 监听 searchData 变化
watch(searchData, (newValue) => {
  emit('update:modelValue', { ...newValue })
}, { deep: true })

// 搜索
const handleSearch = () => {
  emit('search', { ...searchData })
}

// 重置
const handleReset = () => {
  if (!formRef.value) return
  
  // 清空搜索数据
  Object.keys(searchData).forEach(key => {
    searchData[key] = undefined
  })
  
  formRef.value.resetFields()
  emit('reset')
  
  // 重置后自动搜索
  handleSearch()
}

// 切换折叠状态
const toggleCollapse = () => {
  collapsed.value = !collapsed.value
}

// 暴露方法
defineExpose({
  search: handleSearch,
  reset: handleReset
})
</script>

<style scoped>
.search-form {
  background: #fff;
  padding: 16px;
  border-radius: 4px;
  margin-bottom: 16px;
}

:deep(.el-form-item) {
  margin-bottom: 16px;
}

:deep(.el-form-item__label) {
  color: #666;
}
</style>